#ifndef PLOTTER_H
#define PLOTTER_H

#include <QtGui>
#include <iostream>

#include "plotsettings.h"

using namespace std;

// En este ejemplo se implementa un widget Plotter hecho a medida. El widget
// muestra por pantalla dos ejes de coordenadas en los que se representan
// graficamente una o mas curvas de puntos especificadas como vectores de
// coordenadas. El usuario puede seleccionar un area en la imagen clickando en
// un punto del grafico, arrastrando el raton hasta otra posicion y soltando el
// boton, y el Plotter hace un zoom del area seleccionada.

class Plotter : public QWidget
{
    Q_OBJECT

public:
    // Constructor
    Plotter(QWidget *parent = 0);

    // Crea el primer elemento PlotSettings, lo añade al vector zoomStack y
    // llama a refreshPixmap
    void setPlotSettings(const PlotSettings &settings);

    // Inserta en curveMap el vector de puntos definido en data e identificado
    // por id, reemplazando los datos de la curva si ya existe una curva con
    // dicho id. Despues llama a refreshPixmap()
    void setCurveData(int id, const QVector<QPointF> &data);

    // Borra de curveMap los datos identificados por la curva id
    void clearCurve(int id);

    // Devuelve el tamaño minimo recomendado para el widget. Los layout nunca
    // redimensionan un widget a un tamaño menor que el especificado en este
    // metodo, a menos que se establezca la politica QSizePolicy::Ignore.
    QSize minimumSizeHint() const;

    // QWidget::sizeHint devuelve el tamanyo ideal para el widget. Los layout
    // intentan respetar todo lo posible este tamanyo. Por tanto, el valor
    // QSize devuelto debe ajustarse lo mas posible al tamanyo real del widget
    QSize sizeHint() const;

public slots:
    // Slot usado para ampliar la resolucion de la zona seleccionada. Cada vez
    // que el usuario hace un zoom in, se crea y apila un nuevo PlotSettings
    // en el zoomStack y se actualiza la curva de puntos representada
    void zoomIn();

    // Slot usado para deshacer el ultimo zoomIn. Cada vez que el usuario hace
    // un zoom out, se desapila un PlotSettings del zoomStack y se actualiza
    // la curva de puntos mostrada
    void zoomOut();
    QPalette colorTheme(const QColor &base) const;
    void cargar_configuracion();
    void SetLabel(QString Tit,QString xl, QString yl);
protected:
    // El metodo copia la variable miembro pixmap sobre la posicion (x,y) del
    // widget Plotter, dibuja la goma elastica y el rectangulo de foco
    void paintEvent(QPaintEvent *event);

    // El Plotter recibe un evento resizeEvent la primera vez que se crea el
    // widget y cada vez que cambia su tamaño. El metodo se reimplementa para
    // reposicionar los botones zoomInButton y zoomOutButton en la esquina
    // superior derecha sin necesidad de usar un layout manager, lo que mejora
    // el rendimiento de la aplicacion
    void resizeEvent(QResizeEvent *event);

    // El Plotter recibe el evento mousePressEvent cuando el usuario pulsa el
    // boton izquierdo del raton sobre el widget. El metodo se reimplementa
    // para comenzar a dibujar la goma elastica
    void mousePressEvent(QMouseEvent *event);

    // Evento recibido por el widget cuando al menos un boton del raton esta
    // pulsado mientras el usuario mueve el raton. El metodo se reimplementa
    // para ir borrando la goma elastica a medida que se redibuja en las nuevas
    // coordenadas apuntadas por el raton
    void mouseMoveEvent(QMouseEvent *event);

    // El Plotter recibe un evento mouseReleaseEvent cuando el usuario libera el
    // boton izquierdo del raton. La reimplementacion del metodo genera un nuevo
    // objeto PlotterSettings que se almacena en la variable miembro zoomStack y
    // hace el zoom de la zona seleccionada con la goma elastica
    void mouseReleaseEvent(QMouseEvent *event);

    // El Plotter recibe un evento keyPressEvent cuando el usuario pulsa una
    // tecla mientras el Plotter tiene el foco. El metodo se reimplementa para
    // dotar a las teclas Plus y Minus con funcionalidad de zoom y a las teclas
    // Up, Down, Left, y Right con funcionalidad de scroll
    void keyPressEvent(QKeyEvent *event);

    // El Plotter recibe el evento wheelEvent cuando gira la rueda del raton El
    // metodo se reimplementa para dotar a la rueda con funcionalidad de scroll
    void wheelEvent(QWheelEvent *event);
private:
    // Planifica cuatro eventos paintEvent para redibujar cada uno de los lados
    // de la goma elastica en el widget
    void updateRubberBandRegion();

    // Redibuja las curvas y la rejilla de los ejes de coordenadas sobre la
    // variable miembro pixmap. Al final planifica un nuevo evento paintEvent
    // para redibujar el pixmap sobre el widget


    // Dibuja la rejilla detras de los ejes de las curvas de puntos
    void drawGrid(QPainter *painter);

    // Dibuja todas las curvas de puntos definidas en curveMap sobre los ejes
    // coordenados del Plotter
    void drawCurves(QPainter *painter);
    void refreshPixmap();

    enum { Margin = 50 };                   // Constante que proporciona
    // margenes alrededor del grafico

    QToolButton *zoomInButton;              // Boton de zoom in que llama a
    // zoomIn cuando se pulsa
    QToolButton *zoomOutButton;             // Boton de zoom out que llama a
    // zoomOut cuando se pulsa

    QMap <int, QVector<QPointF> > curveMap; // El vector [0, 24, 1, 44, 2, 89]
    // representa la curva definida por
    // los puntos (0, 24),(1, 44),(2, 89)

    QVector <PlotSettings> zoomStack;       // Pila de zoomSettings
    int curZoom;                            // Indice del elemento zoomSettings
    // de la pila zoomStack

    bool rubberBandIsShown;                 // Indica si se esta mostrando la
    // goma elastica

    QRect rubberBandRect;                   // Rectangulo definido por la goma
    // elastica

    QPixmap pixmap;                         // Pixmap donde se dibujan las
                                            // graficas de todas las curvas de
    int color_linea;                                        // puntos en funcion del PlotSettings
    QString Xlabel;
    QString Ylabel;
    QString Titulo;                                       // actualmente seleccionado
};

#endif

